package com.link.base.base.approval.controller;

import com.link.base.user.model.CoreUser;
import com.link.base.base.user.model.User;
import com.link.base.base.approval.exception.ApprovalNeedUserException;
import com.link.base.base.approval.model.Flow;
import com.link.base.base.approval.model.FlowUser;
import com.link.base.base.approval.model.OtherFlowInfo;
import com.link.base.base.approval.service.FlowService;
import com.link.base.base.approval.service.FlowUserService;
import com.link.base.base.approval.service.UsersSelectService;
import com.link.core.cllog.LCLogger;
import com.link.core.basic.annotations.JsonParam;
import com.link.core.basic.controller.BasicController;
import com.link.core.basic.controller.BasicControllerException;
import com.link.core.basic.model.BasicModel;
import com.link.core.basic.query.QueryParams;
import com.link.core.basic.query.Sorter;
import com.link.core.basic.service.BasicService;
import com.link.core.basic.service.BasicServiceException;
import com.link.core.modules.export.ExportFactory;
import com.link.core.modules.export.ExportWriter;
import com.link.core.util.StringUtils;
import com.link.core.util.UserUtil;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Copyright  hande Company. All Rights Reserved.
 *
 * @author unknwon
 * @version 1.0
 * @date: 2018/11/8 14:27
 */

@Controller
@RequestMapping("/link/flow")
public class FlowController extends BasicController<Flow> {

    @Resource
    private FlowService flowService;

    @Resource
    private UsersSelectService usersSelectService;

    @Resource
    private FlowUserService flowUserService;

    private static final Pattern PATTERN = Pattern.compile("(?<=\\[)([^\\(^\\)]+?)(?=\\])");

    @Override
    public BasicService<Flow> getBasicService() {
        return flowService;
    }

    /**
     * 查询待审批流程
     *
     * @param qps
     * @param session
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "/queryFlowPage")
    @ResponseBody
    public Map<String, Object> list(@JsonParam QueryParams qps, HttpSession session, HttpServletRequest request, HttpServletResponse response) {
        Map<String, Object> result = new HashMap<String, Object>(4);
        //按创建时间来排序
        Sorter sorter = new Sorter("created", Sorter.DIR_DESC);
        qps.addSorter(sorter);
        List<Flow> list = null;
        try {
            Flow entity = new Flow();
            qps.invokePreFilterAndSorter();
            qps.preDealSecurity(request);
            Flow t = (Flow) BasicModel.transformClass(entity.getClass(), qps);
            beforQueryAllOrExample(t, request);
            beforQueryExample(t, request);
            CoreUser user = UserUtil.getUser();
            Long userId = user.getId();
            t.setAttr1(userId.toString());
            list = flowService.queryFlowListPage(t);
            result.put("success", true);
            result.put("rows", list);
            result.put("total", getCount(t, list.size()));
        } catch (Exception e) {
            LCLogger.withException(e);
            result.put("success", false);
            result.put("result", e.getMessage());
        }
        return result;
    }

    /**
     * 导出
     *
     * @param entity
     * @param qps
     * @param session
     * @param request
     * @param response
     * @return
     */
    @Override
    @RequestMapping(value = "/queryFlowPage/exportData")
    @ResponseBody
    public Map<String, Object> exportData(@JsonParam Flow entity, @JsonParam QueryParams qps, HttpSession session,
                                          HttpServletRequest request, HttpServletResponse response) {
        LCLogger.info().withMessageKey("queryFlowPage/exportData").withMessage("导出列表...").flush();
        Map<String, Object> result = new HashMap<String, Object>(4);
        try {
            qps.preDealSecurity(request);
            ExportWriter exportWriter;
            String exportType = "xlsx";
            CoreUser user = UserUtil.getUser();
            String exportFileTypeType = qps.getExportFileType();
            if (exportType.equals(exportFileTypeType)) {
                exportWriter = ExportFactory.newExcelInstance(qps);
            } else {
                exportWriter = ExportFactory.newInstance(qps);
            }
            qps.invokePreFilterAndSorter();
            Flow t = BasicModel.transformClass(entity.getClass(), qps);

            t.setAttr1(user.getId().toString());
            List<Flow> list = flowService.queryFlowListPage(t);
            while (!qps.getStopExport()) {
                exportWriter.wirteData(list);
            }
            result.put("success", true);
            result.put("url", exportWriter.getUrlPath());
        } catch (Exception e) {
            LCLogger.withException(e);
            result.put("success", false);
            result.put("result", e.getMessage());
        }
        return result;
    }

    /**
     * 查询我申请审批流程
     *
     * @param qps
     * @param session
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "/queryMyFlowePage")
    @ResponseBody
    public Map<String, Object> queryMyFlowePage(@JsonParam QueryParams qps, HttpSession session,
                                                HttpServletRequest request, HttpServletResponse response) {
        Map<String, Object> result = new HashMap<String, Object>(4);
        List<Flow> list = null;
        try {
            Flow entity = new Flow();
            qps.invokePreFilterAndSorter();
            qps.preDealSecurity(request);
            Flow t = (Flow) BasicModel.transformClass(entity.getClass(), qps);
            beforQueryAllOrExample(t, request);
            beforQueryExample(t, request);
            list = flowService.queryMyFlowListPage(t);
            result.put("success", true);
            result.put("rows", list);
            result.put("total", getCount(t, list.size()));
        } catch (Exception e) {
            LCLogger.withException(e);
            result.put("success", false);
            result.put("result", e.getMessage());
        }
        return result;
    }

    /**
     * 查询我正在运行的申请审批流程
     *
     * @param qps
     * @param session
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "/queryMyRunFlowePage")
    @ResponseBody
    public Map<String, Object> queryMyRunFlowePage(@JsonParam QueryParams qps, HttpSession session,
                                                   HttpServletRequest request, HttpServletResponse response) {
        Map<String, Object> result = new HashMap<String, Object>(4);
        List<Flow> list = null;
        try {
            Flow entity = new Flow();
            qps.invokePreFilterAndSorter();
            qps.preDealSecurity(request);
            Flow t = (Flow) BasicModel.transformClass(entity.getClass(), qps);
            beforQueryAllOrExample(t, request);
            beforQueryExample(t, request);
            list = flowService.queryMyRunFlowListPage(t);
            result.put("success", true);
            result.put("rows", list);
            result.put("total", getCount(t, list.size()));
        } catch (Exception e) {
            LCLogger.withException(e);
            result.put("success", false);
            result.put("result", e.getMessage());
        }
        return result;
    }

    /**
     * 查询已审批流程
     *
     * @param qps
     * @param entity
     * @param session
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "/queryFlowedPage")
    @ResponseBody
    public Map<String, Object> queryFlowedPage(@JsonParam QueryParams qps, @JsonParam Flow entity, HttpSession session,
                                               HttpServletRequest request, HttpServletResponse response) {
        Map<String, Object> result = new HashMap<String, Object>(4);
        //按创建时间来排序
        Sorter sorter = new Sorter("created", Sorter.DIR_DESC);
        qps.addSorter(sorter);
        List<Flow> list = null;
        try {

            qps.invokePreFilterAndSorter();
            qps.preDealSecurity(request);
            Flow t = (Flow) BasicModel.transformClass(entity.getClass(), qps);
            beforQueryAllOrExample(t, request);
            beforQueryExample(t, request);
            CoreUser user = UserUtil.getUser();
            Long userId = user.getId();
            t.setAttr1(userId.toString());
            list = flowService.queryFlowedListPage(t);
            result.put("success", true);
            result.put("rows", list);
            result.put("total", getCount(t, list.size()));
        } catch (Exception e) {
            LCLogger.withException(e);
            result.put("success", false);
            result.put("result", e.getMessage());
        }
        return result;
    }

    @Override
    public void beforUpdate(Flow entity, HttpServletRequest request) throws Exception {
        Date now = new Date();
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        String sflowNodeStart = dateFormat.format(now);
        entity.setFlowNodeStart(sflowNodeStart);
    }

    /**
     * 同意审批
     *
     * @param flowId
     * @param comments
     * @param userId
     * @param otherInfo
     * @param session
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "/agreeApproval")
    @ResponseBody
    public Map<String, Object> agreeApproval(Long flowId, String comments,
                                             Long userId, @JsonParam OtherFlowInfo otherInfo,
                                             HttpSession session, HttpServletRequest request, HttpServletResponse response) {
        Map<String, Object> result = new HashMap<>(4);
        try {
            flowService.agreeApproval(flowId, comments, userId, otherInfo);
            result.put("success", true);
        } catch (ApprovalNeedUserException e) {
            LCLogger.withException(e);
            Matcher match = PATTERN.matcher(e.getMessage());
            List<String> filedList = new ArrayList<>();
            while (match.find()) {
                filedList.add(match.group());
            }
            result.put("success", false);
            result.put("mustSelectUser", true);
            result.put("userId", filedList.get(0));
            result.put("nodeId", filedList.get(1));
            result.put("result", "必须选择用户！");
        } catch (Exception e) {
            LCLogger.withException(e);
            result.put("success", false);
            result.put("result", e.getMessage());
        }
        return result;
    }

    /**
     * 结束审批
     *
     * @param flowId
     * @param comments
     * @param otherInfo
     * @param session
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "/endApproval")
    @ResponseBody
    public Map<String, Object> endApproval(Long flowId, String comments,
                                           @JsonParam OtherFlowInfo otherInfo,
                                           HttpSession session, HttpServletRequest request, HttpServletResponse response) {
        Map<String, Object> result = new HashMap<>(4);
        try {
            flowService.endApproval(flowId, comments, otherInfo);
            result.put("success", true);
        } catch (Exception e) {
            LCLogger.withException(e);
            result.put("success", false);
            result.put("result", e.getMessage());
        }
        return result;
    }

    /**
     * 拒绝审批
     *
     * @param flowId
     * @param comments
     * @param session
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "/refuseApproval")
    @ResponseBody
    public Map<String, Object> refuseApproval(Long flowId, String comments, HttpSession session,
                                              HttpServletRequest request, HttpServletResponse response) {
        Map<String, Object> result = new HashMap<>(4);
        try {
            flowService.refuseApproval(flowId, comments);
            result.put("success", true);
        } catch (Exception e) {
            LCLogger.withException(e);
            result.put("success", false);
            result.put("result", e.getMessage());
        }
        return result;
    }

    /**
     * 继续审批
     *
     * @param flowId
     * @param userId
     * @param comments
     * @param session
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "/goApproval")
    @ResponseBody
    public Map<String, Object> goApproval(Long flowId, Long userId, String comments,
                                          HttpSession session, HttpServletRequest request, HttpServletResponse response) {
        Map<String, Object> result = new HashMap<>(4);
        try {
            flowService.goApproval(flowId, comments, userId);
            result.put("success", true);
        } catch (Exception e) {
            LCLogger.withException(e);
            result.put("success", false);
            result.put("result", e.getMessage());
        }
        return result;
    }

    /**
     * 分页查询用户
     *
     * @param nodeId
     * @param userId
     * @param qps
     * @param session
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "/queryUserSelectPage")
    @ResponseBody
    public Map<String, Object> queryUserSelectPage(Long nodeId, Long userId, @JsonParam QueryParams qps,
                                                   HttpSession session, HttpServletRequest request, HttpServletResponse response) {
        Map<String, Object> result = new HashMap<String, Object>(4);
        try {
            List<User> list = usersSelectService.queryUsersPage(nodeId, userId, qps);
            result.put("success", true);
            result.put("rows", list);
            result.put("total", qps.getTotal());
        } catch (Exception e) {
            LCLogger.withException(e);
            result.put("success", false);
            result.put("result", e.getMessage());
        }
        return result;
    }

    /**
     * 创建审批流程
     *
     * @param entity
     * @param session
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "/createFlow")
    @ResponseBody
    public Map<String, Object> createFlow(@JsonParam Flow entity, HttpSession session, HttpServletRequest request, HttpServletResponse response) {
        Map<String, Object> result = new HashMap<String, Object>(4);
        try {
            Long objectId = Long.parseLong(request.getParameter("objectId"));
            String type = request.getParameter("type");
            Long userId = null;
            if (StringUtils.isNotBlank(request.getParameter("userId"))) {
                userId = Long.parseLong(request.getParameter("userId"));
            }
            String moreFlowName = request.getParameter("moreFlowName");
            if (null == objectId) {
                throw new BasicControllerException("objectId 不能为空");
            }
            if (StringUtils.isBlank(type)) {
                throw new BasicControllerException("type 不能为空");
            }
            if (StringUtils.isBlank(moreFlowName)) {
                throw new BasicControllerException("moreFlowName 不能为空");
            }
            flowService.createFlow(objectId, type, userId, moreFlowName, 0L, "");
            result.put("success", true);
        } catch (Exception e) {
            LCLogger.withException(e);
            result.put("success", false);
            result.put("result", e.getMessage());
        }
        return result;
    }

    /**
     * 更新该审批流程为已读</p>
     *
     * @return
     * @author heqiqian
     */
    @RequestMapping("/read")
    @ResponseBody
    public Map<String, Object> updateRead(Long flowId) {
        Map<String, Object> result = new HashMap<>(4);
        try {
            if (null == flowId) {
                throw new BasicControllerException("流程ID不能为空");
            }
            CoreUser user = UserUtil.getUser();
            FlowUser flowUser = new FlowUser();
            flowUser.setUserId(user.getId());
            flowUser.setFlowId(flowId);
            //设置已读
            flowUser.setReadFlag("Y");
            flowUserService.readFlagUpdate(flowUser);
            result.put("success", true);
        } catch (BasicServiceException e) {
            LCLogger.withException(e);
            result.put("success", false);
            result.put("result", e.getMessage());
            result.put("detailMessage", e.getDetailMessage());
        } catch (Exception e) {
            LCLogger.withException(e);
            result.put("success", false);
            result.put("result", e.getMessage());
        }
        return result;
    }

    /**
     * 同意审批
     *
     * @param flowId
     * @param comments
     * @param userId
     * @param otherInfo
     * @param session
     * @param request
     * @param response
     * @return
     */
    @RequestMapping(value = "/withdrawApproval")
    @ResponseBody
    public Map<String, Object> withdrawApproval(Long flowId, String comments,
                                             Long userId, @JsonParam OtherFlowInfo otherInfo,
                                             HttpSession session, HttpServletRequest request, HttpServletResponse response) {
        Map<String, Object> result = new HashMap<>(4);
        try {
            flowService.withdrawApproval(flowId, comments, otherInfo);
            result.put("success", true);
        } catch (ApprovalNeedUserException e) {
            LCLogger.withException(e);
            Matcher match = PATTERN.matcher(e.getMessage());
            List<String> filedList = new ArrayList<>();
            while (match.find()) {
                filedList.add(match.group());
            }
            result.put("success", false);
            result.put("mustSelectUser", true);
            result.put("userId", filedList.get(0));
            result.put("nodeId", filedList.get(1));
            result.put("result", "必须选择用户！");
        } catch (Exception e) {
            LCLogger.withException(e);
            result.put("success", false);
            result.put("result", e.getMessage());
        }
        return result;
    }
}
